﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Liang.Util.ProtocolDataParser
{
    /// <summary>
    /// 数据解析事件
    /// </summary>
    /// <param name="buffer"></param>
    /// <returns></returns>
    public delegate void ParsedDataHandler(byte[] data);

    /// <summary>
    /// 协议数据解析工具
    /// </summary>
    public class ParserTool : IDisposable
    {
        /// <summary>
        /// 协议数据
        /// </summary>
        private IProtocolData ProtocolData = null;

        /// <summary>
        /// 数据处理线程类
        /// </summary>
        Work m_work = null;

        public event ParsedDataHandler ParsedDataEvent;

        public ParserTool(IProtocolData protocolData)
        {
            ProtocolData = protocolData;

            m_work = new Work();
            // 数据解析线程
            Thread t = new Thread(m_work.DoWork);
            t.IsBackground = true;
            t.Start(this);
        }

        /// <summary>
        /// 添加待解析的数据
        /// </summary>
        /// <param name="data">数据</param>
        public void AddData(byte[] data)
        {
            if (null != m_work)
            {
                m_work.AddData(data);
            }
        }

        /// <summary>
        /// 解析数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private int OnParsingData(byte[] data)
        {
            byte[] outBuffer = null;

            int usedDataLength = data.Length;

            // 如果未提供解析器，则直接把数据交给主程序
            if (null != ProtocolData)
            {
                usedDataLength = ProtocolData.ParsingData(data, out outBuffer);
            }
            else
            {
                outBuffer = data;
            }

            ParsedDataEvent?.Invoke(outBuffer);

            // 返回已处理的数据长度
            return usedDataLength;
        }

        public void Dispose()
        {
            if (null != m_work)
            {
                m_work.Close();
            }
        }

        /// <summary>
        /// 线程处理类
        /// </summary>
        class Work
        {
            /// <summary>
            /// 接收到的数据缓存
            /// </summary>
            List<byte> m_recvBuffer = new List<byte>();

            /// <summary>
            /// 数据同步对象
            /// </summary>
            object m_synDataObject = new object();

            /// <summary>
            /// 是否退出线程
            /// </summary>
            bool m_bQuitThread = false;

            public void Close()
            {
                m_bQuitThread = true;
            }

            public void AddData(byte[] data)
            {
                lock (m_synDataObject)
                {
                    m_recvBuffer.AddRange(data);
                }
            }

            public void DoWork(object obj)
            {
                ParserTool pThis = obj as ParserTool;

                // 已处理的数据长度
                int nUsedLength = 0;

                while (!m_bQuitThread)
                {
                    byte[] tmp = null;

                    lock (m_synDataObject)
                    {
                        if (0 < nUsedLength)
                        {
                            // 删除已处理的数据
                            m_recvBuffer.RemoveRange(0, nUsedLength);
                            nUsedLength = 0;
                        }

                        if (0 < m_recvBuffer.Count)
                        {
                            tmp = m_recvBuffer.ToArray();
                        }
                    }

                    if (null != tmp)
                    {
                        nUsedLength = pThis.OnParsingData(tmp);
                    }

                    Thread.Sleep(30);
                }
            }
        }
    }
}
